#include "bsp_ADC.h"
#include "bsp_Timer.h"

#if 1
// 放到APP层声明
ADC_s ADC_OBEY = {
    .a_STATE = a_ENABLE,               // 状态
    .a_ADCx = ADC1,                    // 目标ADC
    .a_DMAx = DMA1,                    // 目标DMA
    .a_DMA_Channel = LL_DMA_CHANNEL_2, // 目标DMA通道
    .a_Obj_Num = ADC_OBJ_NUM,          // ADC采集对象的数量
    .a_All_Buff = {0},                 // 所有ADC对象采集的数据
                                       // ADC对象结构体数组
    .a_Obj_Struct = {
        [0] = {
            // 温度采集
            .a_Obj_Buff = {0},
            .a_Obj_Value = 0,
        },
    },
};

static void bsp_Adc_Data_Assign(ADC_s *obj);
static void bsp_Adc_Change(ADC_s *obj);
#endif

/************************************************************************************************************************/
/*  @brief  初始化ADC采集
    @return 无
    @property 放到程序初始化位置
*/
void bsp_Adc_Init(ADC_s *obj)
{
    // 配置DMA（ADC）
    LL_DMA_SetPeriphAddress(obj->a_DMAx, obj->a_DMA_Channel, LL_ADC_DMA_GetRegAddr(obj->a_ADCx, LL_ADC_DMA_REG_REGULAR_DATA)); // 设置DMA的外设地址，并绑定ADC的数据转换地址
    LL_DMA_SetMemoryAddress(obj->a_DMAx, obj->a_DMA_Channel, (uint32_t)&obj->a_All_Buff);                                      // DMA获取数据后存放的位置
    LL_DMA_SetDataLength(obj->a_DMAx, obj->a_DMA_Channel, obj->a_Obj_Num * ADC_OBJ_DATA_NUM);                                  // 设置DMA数据长度

    // 配置ADC
    LL_ADC_REG_SetDMATransfer(obj->a_ADCx, LL_ADC_REG_DMA_TRANSFER_NONE); // 设置ADC组定期转换数据传输，默认不通过DMA
    LL_ADC_StartCalibration(obj->a_ADCx);                                 // 校准ADC
    while (LL_ADC_IsCalibrationOnGoing(obj->a_ADCx))                      // 等待校准完成
        ;
    LL_ADC_Enable(obj->a_ADCx);                                                // 软件启动ADC
    LL_ADC_REG_SetDMATransfer(obj->a_ADCx, LL_ADC_REG_DMA_TRANSFER_UNLIMITED); // 设置ADC组定期转换数据传输，DMA+无限模式
    LL_DMA_EnableChannel(obj->a_DMAx, obj->a_DMA_Channel);                     // 使能DMA的通道
    LL_ADC_REG_StartConversion(obj->a_ADCx);                                   // 启动ADC组常规转换
}
/*  @brief  ADC数据分配
    @param  *obj
            ADC对象
    @return 无
    @property 需要定时去分配
*/
static void bsp_Adc_Data_Assign(ADC_s *obj)
{
    uint8_t number_A = 0;
    uint8_t number_B = 0;
    uint32_t Value_A = 0;
    // 分配数据
    for (uint16_t number_C = 0; number_C < ADC_OBJ_NUM * ADC_OBJ_DATA_NUM; number_C++)
    {
        number_A %= obj->a_Obj_Num;
        obj->a_Obj_Struct[number_A].a_Obj_Buff[number_B] = obj->a_All_Buff[number_C];

        if (number_A == (obj->a_Obj_Num - 1))
        {
            number_B++;
        }
        number_A++;
    }
    // 累加算平均值
    for (uint8_t number_D = 0; number_D < ADC_OBJ_NUM; number_D++)
    {
        for (uint8_t number_E = 0; number_E < ADC_OBJ_DATA_NUM; number_E++)
        {
            Value_A += obj->a_Obj_Struct[number_D].a_Obj_Buff[number_E];
        }
        obj->a_Obj_Struct[number_D].a_Obj_Value = Value_A / ADC_OBJ_DATA_NUM; // 求平均值
        Value_A = 0;
    }
}
/*  @brief  ADC触发转换（软件触发方式）
    @return 无
    @property 放在定时器中
*/
static void bsp_Adc_Change(ADC_s *obj)
{
    LL_ADC_REG_StartConversion(obj->a_ADCx); // 软件启动ADC转换
    while (!LL_ADC_IsActiveFlag_EOS(obj->a_ADCx))
    {
        // 等待转换结束
    }
    LL_ADC_ClearFlag_EOS(obj->a_ADCx); // 清除转换结束标志位
}
/************************************************************************************************************************/
/*  @brief  定时触发ADC采集
    @return 无
    @property 放在定时器中
*/
void Ti_BSP_ADC_event(void)
{
    bsp_Adc_Change(&ADC_OBEY);
}
/*  @brief  定时进行数据分配
    @return 无
    @property 放在定时器中
*/
void Ti_BSP_ADC_DATA_event(void)
{
    bsp_Adc_Data_Assign(&ADC_OBEY);
}
/*  @brief  ADC采集调试程序
    @return 无
    @property 无
*/
void bsp_Adc_Debug(void)
{
    bsp_TIM_t Ti_BSP_ADC;
    bsp_TIM_t Ti_BSP_ADC_DATA;

    bsp_Adc_Init(&ADC_OBEY);
    Ti_obj_New(&Ti_BSP_ADC, 10, Ti_RUN, Ti_BSP_ADC_event);
    Ti_obj_New(&Ti_BSP_ADC_DATA, 10 * ADC_OBJ_DATA_NUM, Ti_RUN, Ti_BSP_ADC_DATA_event);

    while (1)
    {
        bsp_Ti_All_Handle();
    }
}
/************************************************************************************************************************/
